/*
* Copyright 2010 ANDAGO INGENIERIA S.L.
*
* Licensed under the EUPL, Version 1.1 only (the "Licence");
* You may not use this work except in compliance with the
* Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in
* writing, software distributed under the Licence is
* distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the Licence for the specific language governing
* permissions and limitations under the Licence.
*/

package com.andago.services;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.net.ssl.HttpsURLConnection;

import com.andago.bean.Measurement;

public class GoogleHealthService {

	private String firstProfileID;
	private String tokenAuth;

	private static String LOGIN_URL = "https://www.google.com/accounts/ClientLogin";
	private static String PROFILE_LIST_URL = "https://www.google.com/h9/feeds/profile/list";
	private static String NOTICES_POST_URL = "https://www.google.com/h9/feeds/register/ui/";

	public GoogleHealthService() {

	}

	/**
	 * Método para comprobar usuario/contraseña
	 * 
	 * @param username
	 * @param password
	 * @return code of the HTTP request (200=OK)
	 * @throws Exception
	 */
	public int loginService(String username, String password) throws Exception {
		// TODO Auto-generated method stub

		URL url = new URL(LOGIN_URL);
		HttpsURLConnection connection = (HttpsURLConnection) url
				.openConnection();
		connection.setDoInput(true);
		connection.setDoOutput(true);
		connection.setRequestMethod("POST");
		HttpURLConnection.setFollowRedirects(true);

		String query = URLEncoder.encode("accountType", "UTF-8") + "="
				+ URLEncoder.encode("HOSTED_OR_GOOGLE", "UTF-8"); // cuenta del
																	// usuario
																	// de google
																	// o no
		query += "&" + URLEncoder.encode("Email", "UTF-8") + "="
				+ URLEncoder.encode(username, "UTF-8"); // direccion de email
		query += "&" + URLEncoder.encode("Passwd", "UTF-8") + "="
				+ URLEncoder.encode(password, "UTF-8");
		query += "&" + URLEncoder.encode("service", "UTF-8") + "="
				+ URLEncoder.encode("weaver", "UTF-8"); // weaver para H9
														// (sandbox de Google
														// Health)
		query += "&" + URLEncoder.encode("source", "UTF-8") + "="
				+ URLEncoder.encode("andago-aloha-1", "UTF-8"); // empresa-aplicacion-version

		connection.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");

		DataOutputStream output = new DataOutputStream(connection
				.getOutputStream());
		output.writeBytes(query);
		output.close();

		int code = connection.getResponseCode();

		DataInputStream input = new DataInputStream(connection.getInputStream());

		String line = "";
		while (!(line.startsWith("Auth"))) {
			line = input.readLine();
		}

		// token de autorizacion para incluir en todas las peticiones
		tokenAuth = line.substring(line.indexOf("="), line.length());

		input.close();

		this.ObtainID();

		return code;

	}

	/**
	 * Método que obtiene el primer ID del usuario (se presupone que solo tiene
	 * un ID)
	 * 
	 * @return firstProfileID
	 * @throws Exception
	 */
	private String ObtainID() throws Exception {

		URL url = new URL(PROFILE_LIST_URL);
		HttpsURLConnection connection = (HttpsURLConnection) url
				.openConnection();
		connection.setDoInput(true);
		connection.setDoOutput(true);
		connection.setRequestMethod("GET");
		HttpURLConnection.setFollowRedirects(true);

		connection.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");
		connection.setRequestProperty("Authorization", "GoogleLogin auth"
				+ tokenAuth);

		DataInputStream input = new DataInputStream(connection.getInputStream());
		firstProfileID = this.parseResponse(input.readLine());

		return firstProfileID;

	}

	/**
	 * Método que extrae el ID del usuario de la respuesta del servidor
	 * 
	 * @param response
	 *            del servidor con la lista de IDs del usuario
	 * @return ID del usuario
	 */
	private String parseResponse(String response) {
		int start = response.indexOf("<content type='text'>");
		int end = response.indexOf("</content>");
		return response.substring(start
				+ new String("<content type='text'>").length(), end);
	}

	/**
	 * Método que envia el CCR a Google Health
	 * 
	 * @param measurementsList
	 *            Lista de mediciones
	 * @return code of the rquest (401= Notice created)
	 * @throws Exception
	 */

	public int sendMeasurements(ArrayList<Measurement> measurementsList)
			throws Exception {
		// TODO Auto-generated method stub

		String ccr = this.generateCCRDocument(measurementsList);

		URL url = new URL(NOTICES_POST_URL + firstProfileID);
		HttpsURLConnection connection = (HttpsURLConnection) url
				.openConnection();
		connection.setDoInput(true);
		connection.setDoOutput(true);
		connection.setRequestMethod("POST");
		HttpURLConnection.setFollowRedirects(true);

		connection.setRequestProperty("Content-Type", "application/atom+xml");
		connection.setRequestProperty("Authorization", "GoogleLogin auth"
				+ tokenAuth);

		String notice = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
		if (ccr != null) {
			// Título y cuerpo de la noticia
			notice = notice
					+ "<entry xmlns=\"http://www.w3.org/2005/Atom\"> <title type=\"text\">Test result received</title><content type=\"text\">Your profile has been updated with new tests</content>";
			notice = notice + ccr;
			notice = notice + "</entry>";
		}

		DataOutputStream output = new DataOutputStream(connection
				.getOutputStream());

		output.writeBytes(notice);
		output.close();
		return connection.getResponseCode();

	}

	/**
	 * Método para la creación del CCR con las mediciones
	 * 
	 * @param measurementsList
	 *            lista de mediciones
	 * @return CCR
	 */
	private String generateCCRDocument(ArrayList<Measurement> measurementsList) {

		String ccr = null;
		if (measurementsList.isEmpty()) {
			System.out.println("Vacio");
			return ccr;
		} else {

			// Header
			ccr = "<ContinuityOfCareRecord xmlns=\"urn:astm-org:CCR\">";
			ccr = ccr + "<CCRDocumentObjectID>Doc</CCRDocumentObjectID>";
			ccr = ccr
					+ "<Language><Text>English</Text><Code><Value>en</Value><CodingSystem>ISO-639-1</CodingSystem></Code></Language>";
			ccr = ccr + "<Version>V1.0</Version>";

			long t = System.currentTimeMillis();
			Date fecha = new Date(t);
			SimpleDateFormat sdf = new SimpleDateFormat(
					"yyyy-MM-dd'T'hh:mm:ssZ");

			ccr = ccr
					+ "<DateTime><Type><Text>Sending date</Text></Type><ExactDateTime>"
					+ sdf.format(fecha) + "</ExactDateTime></DateTime>";
			ccr = ccr + "<Patient><ActorID>Patient</ActorID></Patient>";

			// Body
			ccr = ccr + "<Body>";
			ccr = ccr + "<Results>";
			for (int i = 0; i < measurementsList.size(); i++) {
				ccr = ccr + "<Result>";
				ccr = ccr + "<Test>";

				ccr = ccr
						+ "<DateTime><Type><Text>Collection start date</Text></Type><ExactDateTime>"
						+ measurementsList.get(i).getDate()
						+ "</ExactDateTime></DateTime>";
				ccr = ccr + "<Description><Text>"
						+ measurementsList.get(i).getVariable()
						+ "</Text></Description>";
				ccr = ccr + "<TestResult>";
				ccr = ccr + "<Value>"
						+ measurementsList.get(i).getValue()
						+ "</Value>";
				ccr = ccr + "<Units><Unit>" + measurementsList.get(i).getUnit()
						+ "</Unit></Units>";
				ccr = ccr + "</TestResult>";
				ccr = ccr + "</Test>";
				ccr = ccr + "</Result>";
			}
			ccr = ccr + "</Results>";
			ccr = ccr + "</Body>";

			// Footer
			ccr = ccr
					+ "<Actors><Actor><ActorObjectID>Patient</ActorObjectID></Actor></Actors>";
			ccr = ccr + "</ContinuityOfCareRecord>";

			return ccr;
		}

	}

}
